home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / dis86.arc / DIS86.DOC next >
Text File  |  1986-08-30  |  20KB  |  551 lines

  1.             dis86 - Interactive 8086 Disassembler
  2.                         James R. Van Zandt
  3.  
  4. SYNOPSIS
  5.  
  6. Dis86 is a full-screen, interactive disassembler of object code for the
  7. 8086, 8087, 8088, 80186, 80286, and 80386 (products of Intel), and the
  8. V20 and V30 (products of NEC).  The 80386 disassemblies include 32 bit
  9. operands and addresses.  Dis86 implements the concept of a "current
  10. location" and allows use of the cursor keys to change it.  Code can
  11. come from a .EXE file (in which case the header is properly
  12. interpreted), any other file (assumed to have no header), or anywhere
  13. in main memory (0000:0000 - F000:FFFF).  Dis86 can install changes,
  14. even in an .EXE file, making it a convenient way to install patches. 
  15. Versions are available for the IBM PC (and clones) and Z-100.
  16.  
  17.  
  18. STARTING THE DISASSEMBLER
  19.  
  20. To disassemble a file, give the file name (optionally preceded by a path 
  21. name) on the command line:
  22.  
  23.         A>dis86 foo.exe
  24.  
  25. To disassemble from RAM, use an empty command line:
  26.  
  27.         A>dis86 
  28.  
  29. There are no command line switches.
  30.  
  31.  
  32. FILE HEADER INFORMATION
  33.  
  34. For a .EXE file, the information in the file header will be displayed when
  35. the program is first run and in response to the H command (see below).
  36.  
  37.  
  38. DISPLAY SCREEN
  39.  
  40. During disassembly, the screen will resemble the following:
  41.  
  42.         0000:0100      e9 01 90            jmp            9104                        
  43.         0000:0103      55                  push           bp                          
  44.         0000:0104      8b ec               mov            bp,sp                       
  45.         0000:0106      83 ec 0e            sub            sp,0e                       
  46.         
  47.                                   ...
  48.         
  49.         0000:012C      50                  push           ax                          
  50.         0000:012D      b8 69 00            mov            ax,0069                     
  51.         0000:0130      50                  push           ax                          
  52.         0000:0131      e8 e9 5c            call           5e1d                        
  53.         dis86 1.00 - A SHAREWARE software product  (c) 1986, James R. Van Zandt
  54.         >
  55.         ... 0000:0100  0000:0100  0000:0100  
  56.  
  57. Lines 1 through 21 are the disassembled code.  Each line starts with
  58. the current address, followed by the actual bytes being disassembled. 
  59. The rest of the line is the assembly language equivalent, if any, of
  60. the code.  The display for A (ASCII), B (byte), and D (data) formats is
  61. similar.  All numbers are shown in hexadecimal.
  62.  
  63. Line 22 is a message and prompt line showing, for example, the
  64. arguments needed for some commands.  Line 23 has the prompt.  Typed
  65. characters are echoed on the rest of this line.  Line 24 has three
  66. addresses, which are the first three entries in the stack (see the
  67. 'cursor right' and 'cursor left' commands below).
  68.  
  69.  
  70. CURSOR KEYS
  71.  
  72. The "current location" is the address displayed on the first line
  73. of disassembly.  The cursor keys are used to adjust the current 
  74. location.
  75.  
  76. The up and down cursor keys (8 and 2 on the numeric pad) are used to
  77. move the current location a small amount (note that they are not
  78. inverses):
  79.  
  80.         <up>     moves up by one byte (lower address)
  81.         <down>   moves down by one line (higher address)
  82.  
  83.  
  84. The <pg up> and <pg dn> keys (9 and 3 on the numeric pad) move the
  85. current location by larger amounts.  (These will not move the cursor
  86. out of the disassembly buffer.  Otherwise, they are inverses.):
  87.  
  88.         <pg up>   moves up by 32 bytes (lower address)
  89.         <pg dn>   moves down by 32 bytes (higher address)
  90.  
  91.  
  92. The above keys change only the current location.  Other commands change 
  93. the current location by potentially large amounts, but first save it in 
  94. a stack.  The first three addresses in the stack are shown on the 
  95. command line at the bottom of the screen.
  96.  
  97. If the instruction at the current location is a jump, call, or a
  98. reference to a data location, the cursor right key (6 on the numeric pad)
  99. will push the current location on the stack and go to the referenced
  100. location.  For a data reference, the disassembly format is changed to D
  101. (hex and ASCII).
  102.  
  103.         <right>   follows a jump, call, or data reference
  104.  
  105.  
  106. The cursor left or left arrow key (4 on the numeric pad) will pop the
  107. last address off the stack.  Note that right arrow followed by left
  108. arrow will return you to the same address, whereas left arrow
  109. (returning, let us say, to address X) followed by right arrow will only
  110. return you to the same address if there is an appropriate jump or call
  111. at X.
  112.  
  113.         <left>    pops address stack
  114.  
  115. Aûfter using the right arrow or one of the commands A, B, C, D, or G (in
  116. next section) to go to a new address, and using the left arrow key to
  117. pop the stack, you will sometimes want to return to the previous
  118. address.  The stack no longer holds the address.  However, the left
  119. arrow key saves the current location in a special "previous state"
  120. before popping the stack.
  121.  
  122. To return to the address stored in the "previous state", type shift
  123. right arrow on a Z-100, or control right arrow on an IBM PC.
  124.  
  125.         <shift><right>   returns to "previous state"   (Z-100)
  126.         <cntrl><right>   returns to "previous state"   (IBM)
  127.  
  128.  
  129. In summary, the unshifted keys on the numeric pad are:
  130.  
  131. <home> top of file          ^   up 1 byte         <pg up>  up 32 bytes 
  132.                             |         
  133.  
  134. <--    pop addr stack                             -->      follow jump/call
  135.  
  136.                             |         
  137. <end>  end of file          v  down 1 line        <pg dn>  down 32 bytes  
  138.  
  139.  
  140. <ins>  setup options 
  141.  
  142. On the Z-100, the four keys with arrows on them may be used in addition
  143. to the 2, 4, 6, and 8 on the numeric pad.
  144.  
  145.  
  146. LETTER COMMANDS FOR MOVING THE CURSOR
  147.  
  148. There are five letter commands to change the display format and/or
  149. disassembly address:
  150.  
  151.     A    ASCII data
  152.     B    byte data (hex)
  153.     D    data (both hex bytes and ASCII)
  154.     C    code
  155.     G    goto
  156.  
  157. These commands may be in upper or lower case.  Each may be followed by:
  158.  
  159.     <ret>        Only the display format changes.
  160.  
  161.     A <expression> <ret>
  162.             The current location changes to the specified address.
  163.  
  164.     S <expression> <expression> <expression> <ret>
  165.             The disassembler searches from the current
  166.             address to the end of the buffer for the
  167.             specified sequence of hex bytes.  If an
  168.             expression has a segment specified using the
  169.             ':' operator (below), the segment is ignored.
  170.  
  171.     S T [string] <ret>
  172.             The disassembler searches from the current
  173.             address to the end of the buffer for the
  174.             specified ASCII string.  Cases are not
  175.             distinct, and the high order bit is ignored. 
  176.             The string can also be introduced by a double
  177.             quote.
  178.  
  179.     S R <expression> <ret>
  180.             The disassembler searches from the current
  181.             address to the end of the buffer for a
  182.             reference (jump or call) to the specified
  183.             address.
  184.  
  185. An <expression> can involve any of these items:
  186.  
  187.     hex numbers    (either upper or lower case letters)
  188.     cs, ds, es, ss, fs, gs
  189.             currently assumed segment register values
  190.     $        current location
  191.     @        offset of top address on the stack
  192.  
  193. ...and any of these operators:
  194.  
  195.     + - * /        add, subtract, multiply, divide
  196.     :        separate segment and offset
  197.  
  198. Note that G with no address is a noop.
  199.  
  200.  
  201. OPTIONS
  202.  
  203. The 'O' command or <ins> (0 on the numeric pad) brings up menus for
  204. changing setup options and allows the user to reset the disassembly
  205. window.  Use <space> or <esc> to move to the next screen.
  206.  
  207. The first menu allows the user to select the processor which is
  208. supposed to execute the code.  There is some conflict in op codes
  209. between the V20 and V30 on one hand and the 80286 and 80386 on the
  210. other.  That is, the two families use the same op codes for different
  211. instructions.  Dis86 selects the instruction appropriate for the chip
  212. shown in this menu.  In addition, instructions not implemented by the
  213. indicated chip will be flagged.  The other item on the first menu lets
  214. the user specify 16 or 32 bit mode for the 80386.  In the 16 bit mode
  215. the 80386 is similar to the 8086.  In the 32 bit mode arithmetic is
  216. performed in 32 bit registers and all address offsets are 32 bits. 
  217. (The 80386 itself selects the mode based on a bit in the segment table
  218. entry for the code segment.)
  219.  
  220. The second menu allows the user to indicate the byte value which matches 
  221. any byte in a byte or character search (the "wild card" byte) and select 
  222. the number of bytes displayed on each line for the A, B, or D formats.  
  223. The latter value can also be set using the W command.
  224.  
  225. The last options display is a small map of the code being disassembled
  226. which will resemble the following:
  227.  
  228.         ds= -10
  229.         cs=0000
  230.         |                  ss=0960
  231.         es= -10            |
  232.         | cursor=0000:0453 |
  233.         CCCCCCCCCCCCCCcccccccccccccc
  234.         ^0000:0000
  235.                      ^0000:6144
  236.  
  237. The Cs represent the code being disassembled.  The capital Cs are the
  238. portion of code in the disassembly window (see discussion below).  The
  239. assumed values for the segment registers, the current location (labeled
  240. "cursor"), and the beginning and end addresses of the disassembly
  241. window are also shown.  The window can be adjusted using the right and
  242. left cursor keys.
  243.  
  244. By entering the options menu with the <ins> key and stepping from one
  245. menu to the next with <ret>, you can leave your right hand on the
  246. numeric pad.
  247.  
  248.  
  249. MISCELLANEOUS COMMANDS
  250.  
  251. The 'P' command is used to print a disassembly listing to a file.  The
  252. first time this command is used, it prompts for a file name.  The
  253. default file name is "printout".  To actually send the listing to a
  254. printer, specify the filename "prn".  If the file already exists the
  255. new information will be appended.  The file is automatically closed
  256. before the disassembler exits.  The command also prompts for the
  257. beginning and end addresses of the code to be printed.  The default
  258. addresses print the current screen.  When the printing is finished, the
  259. current address is advanced to the first byte not printed.  Thus, you
  260. can repeat the sequence
  261.  
  262.         P <ret> <ret>
  263.  
  264. to print a large section.
  265.  
  266. Enter 'R' to display and/or change the assumed segment register values.
  267. Entries may be full expressions.  For example, to copy the value from SS 
  268. into DS, use the cursor keys to select the DS register and type "ss".
  269.  
  270. The 'S' command selects a new segment register value for displaying 
  271. addresses.  The new register is shown on the message line.  The actual 
  272. address being disassembled is not changed (see "segmentation" below).
  273.  
  274. The 'W' command is used to set the number of bytes displayed on each
  275. line for the A, B, and D formats.  This is useful for displaying
  276. tables.  For example, when dis86 is executed without a file, it
  277. displays bytes starting at address 0000:0000 and the width is set to
  278. four so each interrupt vector is shown on a separate line.
  279.  
  280. Type '?' to get a series of help screens.  Type <esc> to return to the
  281. disassembly, or any other key to advance to the next screen
  282.  
  283. The 'E' command allows the user to modify the program being
  284. disassembled.  Changes are initially made only in the disassembly
  285. buffer.  Before the buffer is overwritten or the disassembler
  286. terminates, the user is asked whether the changes are to be written to
  287. the file or RAM area being disassembled.
  288.  
  289. Enter 'Q' to stop the disassembler.
  290.  
  291.  
  292. TYPING REQUESTED DATA
  293.  
  294. Many commands supply default entries for requested data.  If you decide
  295. to accept the default, just enter <ret>.  For editing entries,
  296. you can position the cursor using the left and right cursor keys to
  297. move by one character, <home> (7 on the numeric pad) to move to the
  298. left end of the string, or <end> (1 on the numeric pad) to move to the
  299. right end.  Use the <del> or <backspace> keys to delete incorrect
  300. characters, or just type characters to be inserted.  (There is no
  301. "replace" typing mode.) In every case but one, you can also edit the
  302. default entry by making <right>, <end>, or <del> your first keystroke. 
  303. The exception is the default for the byte search function.
  304.  
  305.  
  306. DISASSEMBLY WINDOW
  307.  
  308. The disassembler uses a buffer to hold the code being disassembled. 
  309. For most purposes, this disassembly window is transparent to the user. 
  310. If the user requests an address within the file but outside the
  311. disassembly window, the appropriate code is automatically read in.  The
  312. existence of the window is apparent in only three cases: 
  313.  
  314.     1.  If the disassembler is started near the end of the window and
  315.         reaches the end before it fills the screen, the rest of the
  316.         screen will be left blank.
  317.  
  318.     2.  The searches are done only from the current location to the end
  319.         of the buffer.
  320.  
  321.     3.  If the contents of the buffer has been changed (see 'E'
  322.         command) they are optionally written out before being
  323.         overwritten.
  324.  
  325.  
  326. LOAD ADDRESS
  327.  
  328. Code from a .COM file is displayed as though its Program Segment Prefix
  329. were at 0000:0000 and its load address were 0000:0100.
  330.  
  331. Code from a .EXE file is displayed as though its load address were
  332. 0000:0000.  This puts its Program Segment Prefix is 10 paragraphs or
  333. 100 (hex) bytes lower.  This is somewhat awkward, because the DS and ES
  334. registers are initialized to point to the PSP.  The disassembler
  335. displays this segment value as -10.  The advantage of a load address of
  336. 0000:0000 is that no relocation is necessary.  The bytes displayed are
  337. exactly the same as those in the file.  This also means that the code
  338. can be modified (see below for the 'E' command) and written back to the
  339. file without being "unrelocated".
  340.  
  341.  
  342. SEGMENTATION
  343.  
  344. Addresses are displayed in segment:offset form, using the current
  345. assumed value of the current segment register.  The current segment
  346. register can be selected using the 'S' command to step among the
  347. available registers (CS, SS, DS, ES, FS, and GS - the last two only
  348. with 80386 code).  Changing segment registers or their values does not
  349. move the disassembler cursor.  Only the displayed segment and offset
  350. values will change to reflect the new assumptions.  Legal offsets will
  351. be displayed as a four digit hex number (0000 to FFFF).  Other offsets
  352. (negative or greater than 64K) will also be calculated and displayed
  353. correctly, although they are illegal on the 8086.  Illegal offsets will
  354. have more than four digits.
  355.  
  356. The segment register values are initialized as indicated in the file
  357. header (for .EXE files) or to zero (for other files or RAM).  The
  358. disassembler has no way of determining the values which may be set
  359. during execution.  For example, the initialization code for DeSmet C
  360. programs resets DS to the same value as the initial SS before executing
  361. main().
  362.  
  363. The assumed segment register values can be altered in two ways.  Any
  364. segment register can be changed using the register menu reached by the
  365. 'R' command.  In addition, when the right arrow key is used to follow a
  366. far call or jump, the new code segment value is loaded into the CS
  367. register.  When the user specifies a new segment value on an A, B, C, D, 
  368. or G command, that value is used for subsequent displays but none of the 
  369. assumed segment register values is changed.
  370.  
  371. The segmentation models of the protected modes of the 80286 and 80386 
  372. are not supported.
  373.  
  374.  
  375. ALIGNMENT
  376.  
  377. Dis86 will correctly disassemble code if started on the first byte of
  378. an instruction.  If started in the middle of an instruction, it will
  379. disassemble that instruction and perhaps several more incorrectly.  In
  380. this case the disassembler is said to be out of alignment with the
  381. object code.  The disassembler will tend to correct its alignment if it
  382. continues long enough.  8086 instructions tend to be longer than, for
  383. example, those for the 8080, so the disassembler will tend to stay out
  384. of alignment for more instructions.  Generally speaking, the alignment
  385. will be correct after the first half dozen lines.
  386.  
  387.  
  388. SUMMARY
  389.  
  390. Here are all the letter commands:
  391.  
  392. A nnnn     ASCII data             
  393. B nnnn     byte data (hex)        
  394. C nnnn     code (disassembly)     
  395. D nnnn     data (hex and ASCII)   
  396. E          enter new data (follow with a hex expression for each new byte)
  397.  
  398. G nnnn     goto address nnnn      
  399. H          display file header information (.EXE files only)
  400. O          change setup options
  401. P          print disassembly listing to file  
  402. Q          quit to DOS 
  403.  
  404. R          change segment register values
  405. S          select new segment register 
  406. W          set bytes of data per line for A, B, and D formats
  407. X          exchange current address (at top of screen) with top of stack  
  408. ?          display help screens  
  409.  
  410.  
  411.  
  412. EXAMPLE 1
  413.  
  414. In the examples, <left>, <right>, <up>, and <down> refer to the four
  415. cursor keys (4, 6, 8, and 2 on the numeric pad, plus the four arrow keys 
  416. on the Z-100 keyboard).  <pg up> and <pg dn> refer to 9 and 3 on the
  417. numeric pad.
  418.  
  419. To investigate the bootstrap code, type
  420.  
  421.     A>dis86 <ret>
  422.  
  423. and press
  424.  
  425.     <space>
  426.  
  427. to advance to the disassembly display (which will be the interrupt
  428. vectors).  Next type
  429.  
  430.     c a ffff:0000 <ret>
  431.  
  432. (for Code format at the Address ffff:0000).  On an IBM, the ROM release
  433. date and machine ID appear in the last 16 bytes of the ROM.  To see them, 
  434. type
  435.  
  436.     D <ret>
  437.  
  438. The release data is at addresses ffff:0005 - ffff:000c in ASCII.  The
  439. machine ID is at ffff:000e.  Some of the possible values are:
  440.  
  441.     ff    IBM PC
  442.     fe    IBM XT and Portable IBM PC
  443.     fd    IBM PCjr
  444.     fc    IBM AT
  445.     2d    Compaq
  446.     9a    Compaq-Plus
  447.  
  448. Return to code format by typing 
  449.  
  450.     C <ret>
  451.  
  452. One of the instructions displayed will almost certainly be a jump.  If
  453. so, press
  454.  
  455.     <down>
  456.  
  457. enough times to bring the jump to the top line, then
  458.  
  459.     <right>
  460.  
  461. to follow the jump.  Note that the previous addresses were pushed onto
  462. the stack, as shown on the bottom line.  To return to the most recent
  463. address, press
  464.  
  465.     <left>
  466.  
  467. To leave the disassembler, press
  468.  
  469.     Q
  470.  
  471.  
  472. EXAMPLE 2
  473.  
  474. For a second example, let us disassemble the disassembler itself. 
  475. Begin by typing
  476.  
  477.     A>dis86 dis86.exe <ret>
  478.  
  479. Note the header information, including the entry point of 0000:0000 and
  480. the initial stack location of approximately 09e0:9eb8.  Proceed to the
  481. disassembly screen by typing
  482.  
  483.     <space>
  484.  
  485. The disassembler starts in C (code) format at the entry point, which is
  486. a jump to the initialization code.  To follow the jump, type
  487.  
  488.     <right>
  489.  
  490. One of the early instructions in the initialization code refers to the
  491. first location in the stack segment.  Bring this location to the top of
  492. the screen by typing
  493.  
  494.     <pg dn> <down> <down>
  495.  
  496. and follow the reference by typing
  497.  
  498.     <right>
  499.  
  500. Since it was a data reference, the disassembler automatically switched
  501. to D (data) format.  Note that the two previous addresses have been
  502. pushed onto the stack, as shown at the bottom of the screen.  Return to
  503. the most recent one by typing
  504.  
  505.     <left>
  506.  
  507. The initialization code gets rather involved, but one of its functions
  508. is to initialize DS to the same value as SS.  To reflect this, use the
  509. R command:
  510.  
  511.     R
  512.  
  513. DS is the first register in the list, so you need only enter the
  514. appropriate value:
  515.  
  516.     ss <ret> <space>
  517.  
  518. The code for the main program immediately followed the jump at
  519. 0000:0000.  To return there, type
  520.  
  521.     <left>
  522.  
  523. Send a copy of this screen to the file "printout" by typing
  524.  
  525.     P <ret> <ret> <ret>
  526.  
  527. To inspect the data segment, type
  528.  
  529.     A ds:0 <ret>
  530.  
  531. To display more characters on each line, use the W command:
  532.  
  533.     W 60 <ret>
  534.  
  535. Use the search command to find one of the messages:
  536.  
  537.     G S T hime <ret>
  538.  
  539. This string won't be found.  To correct the spelling to "home" and try
  540. again, type
  541.  
  542.     G S T <right> o <del> <ret>
  543.  
  544. Once again, leave the disassembler by pressing
  545.  
  546.     Q
  547.  
  548.  
  549.  
  550.  
  551.